package org.jfk.tbox.net;

import java.util.Date;

import org.jfk.core.utils.ByteUtils;

public abstract class TboxMsg {
	public byte[] header = {0x46,0x4C,0x43,0x2E};
	public byte[] orgData = null;
	public int testFlag = 0;
	public int msgSize = 0;
	public int dptMsgSize = 0;
	public int dptMSecCtxVer = 0;
	public Date eventCreateTime = null;
	public String eventId = "000000000000";
	public String appId = null;
	public int msgId = 0;
	public int msgUpCount = 0;
	public int msgDownCount = 0;
	public int appDataLength = 0;
	public int result = 0;
	public String vechicleTypeCode = null;
	public String vin = null;
	public String sn = null;
	public String imsi = null;
	public String seed;
	public int appDataSecCtxVer = 0;
	public byte[] appData = null;
	public byte checkSum = 0;
	
	
	byte[] _head = new byte[4];
	byte[] _testFlag = new byte[1];
	byte[] _msgSize = new byte[2];
	byte[] _dptMsgSize = new byte[2];
	byte[] _dptMSecCtxVer = new byte[1];
	byte[] _eventCreateTime = new byte[4];
	byte[] _eventId = new byte[6];
	byte[] _appId = new byte[2];
	byte[] _msgId = new byte[2];
	byte[] _msgCount = new byte[2];
	byte[] _appLength = new byte[2];
	byte[] _result = new byte[2];
	byte[] _vechicleTypeCode = new byte[4];
	byte[] _vin = new byte[17];
	byte[] _sn = new byte[26];
	byte[] _imsi = new byte[15];
	byte[] _seed = new byte[4];
	byte[] _appDataSecCtxVer = new byte[1];
	byte[] _appData = null;
	byte[] _checknum = new byte[1];
	
	public void loadData(byte[] data){

		byte[] a = data;
		
		this.orgData = a;
		this.testFlag = a[4];
		byte[] tmp1 = {a[5],a[6]};
		this.msgSize = ByteUtils.byte2ToInt(tmp1);
		byte[] tmp2 = {a[7],a[8]};
		this.dptMsgSize = ByteUtils.byte2ToInt(tmp2);
		this.dptMSecCtxVer = a[9];
		byte[] tmp3 = {a[10],a[11],a[12],a[13]};
		long time = ByteUtils.byte4Tolong(tmp3);
		//int a = ByteUtils.byte4ToInt(aa);
		this.eventCreateTime = new Date(0-(8*60*60*1000)+time*1000);
		byte[] tmp4 = {a[14],a[15],a[16],a[17],a[18],a[19]};
		this.eventId = ByteUtils.byteToHexString(tmp4);
		byte[] tmp5 = {a[20],a[21]};
		this.appId = ByteUtils.byteToHexString(tmp5);
		byte[] tmp6 = {a[22],a[23]};
		this.msgId = ByteUtils.byte2ToInt(tmp6);
		this.msgUpCount = a[24]; 
		this.msgDownCount = a[25];
		byte[] tmp7 = {a[26],a[27]};
		this.appDataLength = ByteUtils.byte2ToInt(tmp7);
		byte[] tmp8 = {a[28],a[29]};
		this.result = ByteUtils.byte2ToInt(tmp8);
		byte[] tmp9 = {a[30],a[31],a[32],a[33]};
		this.vechicleTypeCode = ByteUtils.byteToHexString(tmp9);
		byte[] tmp10 = {a[34],a[35],a[36],a[37],a[38],a[39],a[40],a[41],a[42],a[43],a[44],a[45],a[46],a[47],a[48],a[49],a[50]};
		this.vin = ByteUtils.bytesToASCII(tmp10);
		byte[] tmp11 = {a[51],a[52],a[53],a[54],a[55],a[56],a[57],a[58],a[59],a[60],a[61],a[62],a[63],a[64],a[65],a[66],a[67],a[68],a[69],a[70],a[71],a[72],a[73],a[74],a[75],a[76]};
		this.sn = ByteUtils.bytesToASCII(tmp11);
		byte[] tmp12 = {a[77],a[78],a[79],a[80],a[81],a[82],a[83],a[84],a[85],a[86],a[87],a[88],a[89],a[90],a[91]};
		this.imsi = ByteUtils.bytesToASCII(tmp12);
		byte[] tmp13 = {a[92],a[93],a[94],a[95]};
		this.seed = ByteUtils.bytesToASCII(tmp13);
		this.appDataSecCtxVer = a[96];
		byte[] tmp14 = new byte[this.appDataLength];
		for (int i = 0 ; i < this.appDataLength ; i++){
			tmp14[i] = a[97+i];
		}
		this.appData = tmp14;
		this.checkSum = a[96+this.appDataLength+1];
		
		if (a.length != 98+this.appDataLength){//MessageHeader+appDataLenght+checkSum
			throw new RuntimeException("报文长度异常");
		}
		
		byte[] tmp15 = new byte[a.length-1];
		
		System.arraycopy(a, 0, tmp15, 0, tmp15.length);
		byte crc = ByteUtils.genCRC16(tmp15);
		
		if (crc != this.checkSum){
			throw new RuntimeException("checkSum错误");
		}		

	}
	
	/**
	 * 生成该消息回包数据
	 * @return
	 */
	public abstract byte[] getResp();
	
	/**
	 * 将appData转为byte[]
	 * @return
	 */
	public abstract byte[] getAppData();
	
	
	public String toString(){
		int length = orgData == null ? 0 : orgData.length;
		String s = "appId = "+ appId
				+" ,msgId = "+ msgId
				+" ,eventId = "+ eventId
				+" ,sn = "+ sn
				+" ,imsi = "+ imsi
				+" ,vin = "+ vin
				+" ,eventCreateTime = "+ eventCreateTime
				+" ,msgFullLengh = "+ length
				+" ,appData = "+ ByteUtils.byteToHexString(appData)
				;
				
		return s;
	}
	
	
	public byte[] toBytes(){
		
		//由子类将各自的appData转为byte[]
		_appData = this.getAppData();
		
		//计算Dispatcher Message Size
		int i_dptMsgSize = 0 
				+ _eventCreateTime.length
				+ _eventId.length
				+ _appId.length
				+ _msgId.length
				+ _msgCount.length
				+ _appLength.length
				+ _result.length
				+ _vechicleTypeCode.length
				+ _vin.length
				+ _sn.length
				+ _imsi.length
				+ _seed.length
				+ _appDataSecCtxVer.length;
		//计算Message Size
		int i_msgSize = i_dptMsgSize + _appData.length;
		this.dptMsgSize = i_dptMsgSize;
		this.msgSize = i_msgSize;
		//计算包总长度
		int i_totalSize = 0
				+ _head.length
				+ _testFlag.length
				+ _msgSize.length
				+ _dptMsgSize.length
				+ _dptMSecCtxVer.length
				+ i_msgSize
				+ _checknum.length;		
		
		//将所有属性逐个转为byte[]
		_head = this.header;
		_testFlag[0] = (byte)this.testFlag;
		_msgSize = ByteUtils.intToWord(this.msgSize);
		_dptMsgSize = ByteUtils.intToWord(this.dptMsgSize);
		_dptMSecCtxVer[0] = (byte)this.dptMSecCtxVer;
		_eventCreateTime = ByteUtils.longToDWord(this.eventCreateTime.getTime()/1000);
		_eventId = ByteUtils.hexStringToBytes("000000000000");
		_appId = ByteUtils.hexStringToBytes(this.appId);
		_msgId = ByteUtils.intToWord(this.msgId);
		_msgCount[0] = (byte)this.msgUpCount;
		_msgCount[1] = (byte)this.msgDownCount;
		_appLength = ByteUtils.intToWord(_appData.length);
		_result = ByteUtils.intToWord(0);
		_vechicleTypeCode = ByteUtils.hexStringToBytes(this.vechicleTypeCode);
		_vin = ByteUtils.strToASCII(this.vin);
		_sn = ByteUtils.strToASCII(this.sn);
		_imsi = ByteUtils.strToASCII(this.imsi);
		_seed = ByteUtils.hexStringToBytes(this.seed);
		_appDataSecCtxVer[0] = (byte) this.appDataSecCtxVer;
		

		
		//拼装完整的byte[]
		byte[] b_resp = new byte[i_totalSize];
		int idx = 0;
		System.arraycopy(_head, 0, b_resp, idx, _head.length);
		idx = idx + _head.length;

		System.arraycopy(_testFlag, 0, b_resp, idx, _testFlag.length);
		idx = idx + _testFlag.length;
		
		System.arraycopy(_msgSize, 0, b_resp, idx, _msgSize.length);
		idx = idx + _msgSize.length;
		
		System.arraycopy(_dptMsgSize, 0, b_resp, idx, _dptMsgSize.length);
		idx = idx + _dptMsgSize.length;
		
		System.arraycopy(_dptMSecCtxVer, 0, b_resp, idx, _dptMSecCtxVer.length);
		idx = idx + _dptMSecCtxVer.length;
		
		System.arraycopy(_eventCreateTime, 0, b_resp, idx, _eventCreateTime.length);
		idx = idx + _eventCreateTime.length;
		
		System.arraycopy(_eventId, 0, b_resp, idx, _eventId.length);
		idx = idx + _eventId.length;
		
		System.arraycopy(_appId, 0, b_resp, idx, _appId.length);
		idx = idx + _appId.length;
		
		System.arraycopy(_msgId, 0, b_resp, idx, _msgId.length);
		idx = idx + _msgId.length;
		
		System.arraycopy(_msgCount, 0, b_resp, idx, _msgCount.length);
		idx = idx + _msgCount.length;

		System.arraycopy(_appLength, 0, b_resp, idx, _appLength.length);
		idx = idx + _appLength.length;
		
		System.arraycopy(_result, 0, b_resp, idx, _result.length);
		idx = idx + _result.length;
		
		System.arraycopy(_vechicleTypeCode, 0, b_resp, idx, _vechicleTypeCode.length);
		idx = idx + _vechicleTypeCode.length;
		
		System.arraycopy(_vin, 0, b_resp, idx, _vin.length);
		idx = idx + _vin.length;
		
		System.arraycopy(_sn, 0, b_resp, idx, _sn.length);
		idx = idx + _sn.length;
		
		System.arraycopy(_imsi, 0, b_resp, idx, _imsi.length);
		idx = idx + _imsi.length;
		
		System.arraycopy(_seed, 0, b_resp, idx, _seed.length);
		idx = idx + _seed.length;
		
		System.arraycopy(_appDataSecCtxVer, 0, b_resp, idx, _appDataSecCtxVer.length);
		idx = idx + _appDataSecCtxVer.length;
		
		System.arraycopy(_appData, 0, b_resp, idx, _appData.length);
		idx = idx + _appData.length;
		
		//生成校验码
		byte[] checkData = new byte[b_resp.length - 1];
		System.arraycopy(b_resp, 0, checkData, 0, checkData.length);
		byte crc = ByteUtils.genCRC16(checkData);

		_checknum[0] = crc;
		System.arraycopy(_checknum, 0, b_resp, idx, _checknum.length);
		idx = idx + _checknum.length;		
		
		return b_resp;
	}
	
	public TboxMsg initResp(TboxMsg msg){
		if (msg == null){
			return null;
		}
		msg.vin = this.vin;
		msg.sn = this.sn;
		msg.imsi = this.imsi;
		msg.seed = this.seed;
		msg.vechicleTypeCode = this.vechicleTypeCode;
		msg.eventCreateTime = new Date(System.currentTimeMillis());
		return msg;
	}

	public String getEventDesc(){
		return this.appId;
	}
}
